class user
{
public:
	//User					UsrObj;				//User Object
	profile					Nfo;				//User Info
	IAnimatedMesh			Msh;				//User Mesh
	IAnimatedMeshSceneNode	Nde;				//User Scenenode
	vector3df				Elp;				//User Collision Ellipsoid
	ITexture				Skn;				//User Skin Texture
	vector3df				Vlc;				//User Velocity
	float					Mmt;				//User Momentum
	float					Fct;				//User Friction
	stringw					Ipt;				//User Input Key, Joy, Net
	joystick				Joy;				//User Joystick
	vector2df				ConDir;				//Direction of Joystick
	float					ConSpd;				//Extent of Joystick
	vector3df				Dsp;				//Displacement from Last Position
	vector3df				LasLasPos;			//Last Last Position
	vector3df				LasPos;				//Last Position
	stringw					Ste;				//Primary User State
	stringw					Evt;				//Secondary User State
	int						EvtTim;  			//Event Timer Ms
	float					Hth;				//User Health 1000 Max
	float					Stm;				//User Stamina 1000 Max
	int						Kil;				//User Kills
	stringw					Nam;				//User Name
	stringw					Wpn;				//User Weapon Name, selected Weapon Slot
	stringw					Itm;				//User Item Name, selected Item Slot
	int						Ani;				//User Animation
	int						AniLas;				//Last Animation Frame
	int						AniInf[2][14]	=	//Animation Info Table
		// Stnd| Walk|	Run| Jump| Flip| Sprn| Leap| Crwl| Crch| Clmb| Hi-5| Fall| Impt|  Die| Dead| Voic|
		{{    1,   42,    1,  120,   89,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}, //Start
		{    41,   88,    1,  153,  119,    0,    0,    0,    0,    0,	  0,    0,    0,    0,    0}};//End
	int						Bmp;				//Bumping Collision Flag
	int						SprTim;				//Spring Timer
	int						Lnd;				//Landing Collision Flag
	triangle3df				Tri;				//Collision Result Triangle
	//Void					ObjArr[5, 5, 0]	=	//Object Array
	//	IntObj | ActObj | VisObj | SlcObj | Obj
	//	-------|--------|--------|--------|-------
	//0|Ent    |Ent  	|Ent	 |Ent	  |Ent
	//1|Prp    |Prp  	|Prp	 |Prp	  |Prp
	//2|Bak    |Bak  	|Bak	 |Bak	  |Bak
	//3|Clc    |Clc  	|Clc	 |Clc	  |Clc
	//4|Prj    |Prj  	|Prj	 |Prj	  |Prj
	list					IntObj;				//Interactive Objects
	list					ActObj;				//Active Objects
	list					VisObj;				//Visible Objects
	list					InaObj;				//Inactive Objects
	list					SlcObj;				//Selected Objects

	user( profile, vector3df, vector2df, IAnimatedMesh, stringw, stringw, stringw, stringw );
	Update()
	{
		switch( this->Ste );
		{
			case "Stand":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if( Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas = Nde.getFrameNr();
						EvtTim -= 1000 / LastFPS;
					}
				}
				if( Mmt > 0 ) Mmt -= 0.25;	//Set Momentum to null

				//Animation
				if(	Evt )
				{
					if(	Ani )
					{
						Ani	= 0;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				if(	Vlc.getX() && Vlc.getZ()) Land( 0.25 );
				Collide();

				//Sound
				break;

			case "Walk":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;

					//Elapse Event Animation

						AniLas = Nde.getFrameNr();
						EvtTim -= 1000 / LastFPS;
					}
				}
				if(	receiver.IsKeyDownUp( EKEY_KEY_W ) ||
					receiver.IsKeyDownUp( EKEY_KEY_S ) ||
					receiver.IsKeyDownUp( EKEY_KEY_A ) ||
					receiver.IsKeyDownUp( EKEY_KEY_D ))
				{
					Ste	= "Stand";
				}
				else if( Mmt <= 3.5 )				//Increase Speed of User
				{
					if(	Mmt < 3.5 ) Mmt += 0.25;	//Increase Momentum
				}

				//Animation
				if(	Evt )
				{
					if(	Ani ! 1 )
					{
						Ani = 1;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Move( Mmt );
				Collide();

				//Sound
				break;

			case "Run":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	receiver.IsKeyDownUp( EKEY_KEY_W ) ||
					receiver.IsKeyDownUp( EKEY_KEY_S ) ||
					receiver.IsKeyDownUp( EKEY_KEY_A ) ||
					receiver.IsKeyDownUp( EKEY_KEY_D ))
				{
					Ste	= "Stand";
				}
				else if( receiver.IsKeyDownUp( EKEY_SHIFT ))
				{
					Ste	= "Walk";
				}
				else if( Mmt <= 5)	//Increase Speed of User
				{
					if(	Mmt < 5 ) Mmt += 0.25;	//Increase Momentum
				}

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 2 )
					{
						Ani	= 2;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Move( Mmt );
				Collide();

				//Sound
				break;

			case "Crouch":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	receiver.IsKeyDownUp( EKEY_CONTROL ))
				{
					Ste = "Stand";
				}
				else if( Mmt )
				{
					if(	Mmt < 0 ) Mmt = 0;		//Set Momentum to null
					else Mmt -= 0.25;			//Subtract Friction From Momentumx
				}

				//Animation
				if(	Evt == "" )
				{
					if(	Ani )
					{
						Ani	= 8;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				this->Land( 0.25 );

				//Sound
				break;

			case "Crawl":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	receiver.IsKeyDownUp( EKEY_KEY_W ) ||
					receiver.IsKeyDownUp( EKEY_KEY_S ) ||
					receiver.IsKeyDownUp( EKEY_KEY_A ) ||
					receiver.IsKeyDownUp( EKEY_KEY_D ) ||
					receiver.IsKeyDownUp( EKEY_CONTROL ))
				{
					Ste	= "Crouch";
				}

				//Animation
				if(	Evt )
				{
					if(	Ani ! 7 )
					{
						Ani = 7;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Move( 2 );
				Collide();

				//Sound
				break;
			case "Jump":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	Mmt ) Mmt -= 0.25;								//Set Momentum to null
				if(	SprTim <= 0 && Bmp == true ) SprTim = 1000;		//Start Spring Timer
				if(	SprTim > 0 ) SprTim -= 1000 / LastFPS;			//Update Spring Timer
				if(	SprTim <= 0 && Bmp == false ) SprTim = 0;		//Stop Spring Timer
				//if( Lnd == true ) Ste = "Stand";					//Only Needed for Testing
				if(	Lnd == true ) Land( 0.25 )	;					//* Need to Find Deaccelleration Value

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 3 )
					{
						Ani = 3;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Glide( 4 );
				Collide();

				//Sound
				break;

			case "Flip":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	Mmt ) Mmt -= 0.25;								//* Incomplete, May Not be Nessasary
				if(	SprTim <= 0 && Bmp == true ) SprTim = 1000;	//Start Spring Timer
				if(	SprTim > 0 ) SprTim -= 1000 / LastFPS;		//Update Spring Timer
				if(	SprTim <= 0 && Bmp == false ) SprTim = 0;	//Stop Spring Timer
				//if( Lnd == true ) Ste = "Stand";					//Only Needed for Testing
				if(	Lnd == true ) Land( 0.25 );					//* Need to Find Deaccelleration Value

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 4 )
					{
						Ani = 4;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Glide( 3 );
				Collide();

				//Sound
				break;

			case "Leap":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	Mmt ) Mmt -= 0.25;				//* Incomplete, May Not be Nessasary
				if(	Lnd == true ) Ste = "Stand";	//* Needed For Testing Only
				//if( Lnd == true ) Land();			//* Need to Find Deaccelleration Value

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 6 )
					{
						Ani = 6;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Glide( 3 );
				Collide();

				//Sound
				break;

			case "Spring":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	Mmt ) Mmt -= 0.25;				//* Incomplete, May Not be Nessasary
				if(	Lnd == true ) Ste = "Stand";	//* Needed For Testing Only
				//if( Lnd == true ) Land();			//* Need to Find Deaccelleration Value

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 5 )
					{
						Ani = 5;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Glide( 1 );
				Collide();

				//Sound
				break;

			case "Climb":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas = Nde.getFrameNr();
						EvtTim -= 1000 / LastFPS;
					}
				}

				if(	receiver.IsKeyDown( EKEY_KEY_W ))
				{
					Climb( 2.5 );
				}
				else if( receiver.IsKeyDown( EKEY_KEY_S ))
				{
					Climb( 3.5 );
				}

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 9 )
					{
						Ani	= 9;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}
				if(	Vlc.getY() > 0 )
				{
					Nde.setAnimationSpeed( 12 );
				}
				else if( Vlc.getY() < 0 )
				{
					Nde.setAnimationSpeed( -12 );
				}
				else
				{
					Nde.setAnimationSpeed( 0 );
				}

				//Sound
				break;

			case "Hang":
				//Logic
				Nde.getPosition();
				//Animation
				break;

			case "Fall":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}
				if(	Mmt ) Mmt -= 0.25;				//* Incomplete, May Not be Nessasary
				if(	Lnd == true ) Ste = "Stand";	//* Need to Find Deaccelleration Value

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 10 )
					{
						Ani	= 10;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
						//*Change Ellipsoid Dimensions
					}
				}

				//Physics
				Glide( 2 );
				Collide();

				//Sound
				break;

			case "Dead":
				//Logic
				if(	Evt )
				{
					//End of Event Animation
					if(	Nde.getFrameNr() < AniLas && EvtTim <= 0 )
					{
						Evt		= "";
						AniLas	= 0;
						EvtTim	= 0;
					}
					//Elapse Event Animation
					else
					{
						AniLas	= Nde.getFrameNr();
						EvtTim	-= 1000 / LastFPS;
					}
				}

				//Animation
				if(	Evt == "" )
				{
					if(	Ani ! 12 )
					{
						Ani	= 12;
						Nde.setFrameLoop( AniInf[Ani][1], AniInf[Ani][2] );
					}
				}
				break;
			default:
		}
	};

	Move( float Spd )
	{
		//Physics
		matrix4		M1;									//Matrix 1
		matrix4		M2;									//Matrix 2
		vector3df	UsrPos	= this->Nde.GetPosition();	//User Position
		vector3df	CamPos	=							//Camera Position
			smgr->getActiveCamera()->getPosition();
		vector3df	Fwd		=							//Forward Vector
			vector3df<s32>( 0, 0, Spd * ConSpd );	
		float		CamAng	=							//Camera Angle from User
			vector2df<s32>( UsrPos.getX() - CamPos.getX(), UsrPos.getZ() - CamPos.getZ()).getAngle();

		//* Rotate to Terrain Surface X and Y Angle
		//* Check if Player is Landed on the Ground
		M1.setRotationDegrees( vector3df<s32>( 0, CamAng, 0 ));
		M2.setRotationDegrees( vector3df<s32>( 0, ConDir.getAngle(), 0 ));
		M1.MultEq( M2 );
		M1.transformVect( Fwd );
		Nde.SetRotation( M1.getRotationDegrees());
		Vlc.setX( Fwd.getX());
		Vlc.setZ( Fwd.getZ());
	}
	Glide( float Drf )
	{
		//Physics
		matrix4	M1;		//Rotation Matrix
		matrix4	M2;		//Trasformation Matrix
		vector3df	Fwd	= vector3df<s32>( 0, 0, Drf * ConSpd );	//Forward Vector

		//Test Rotate Forward by Control Direction
		//Fwd.rotateXZBy( Nde.GetRotation().getY() + ConDir.getAngle(), Nde.GetPosition())

		//Multiplay Control Direction by Momentum
		M1.setRotationDegrees( vector3df<s32>( 0, Nde.GetRotation().getY(), 0 ));
		M2.setRotationDegrees( vector3df<s32>( 0, ConDir.getAngle(), 0 ));
		M1.MultEq( M2 );
		M1.transformVect( Fwd );

		//Add Drift to Velocity
		Nde.SetPosition( Nde.GetPosition().Plus( Fwd ));
	}
	Land( float Dcl )
	{
		//Find Motion Velocity, Rotatate 180 Degrees, and Then Subtract Deceleration Speed
		if(	vector3df<s32>( Vlc.getX(), 0, Vlc.getZ()).getLength())
		{
			//Find Motion Velocity
			vector3df	MotVel;								//Motion Velocity Vector

			MotVel.setY( vector2df<s32>( Vlc.getX(), Vlc.getZ()).getAngle());	//Y Angle

			//Rotate 180 Degrees
			matrix4	M;
			vector3df	Fwd	= vector3df<s32>( 0, 0, Dcl );		//Rate of Deceleration

			M.setRotationDegrees( MotVel.Minus( vector3df<s32>( 0, - 90, 0 )));
			M.rotateVect( Fwd );

			//Subtract Deceleration Vector
			Vlc.MinusEq( vector3df<s32>( Fwd.getX(), 0, Fwd.getZ()));
			MotVelTst = vector3df<s32>( Fwd.getX(), 0, Fwd.getZ()).Mult( 100 );	//* Test Variable

			//Check if Vlc is in Resting Range and Set to Zero
			if(	vector2df<s32>( Vlc.getX(), Vlc.getZ()).getLength() <= 0.75 ) Vlc = vector3df<s32>( 0, Vlc.getY(), 0 );
		}
	}
	Collide( list Body )
	{
		//Gravity
		if(	Vlc.getY() > -6 )
		{
			Vlc.MinusEq( Map.Grv );
		}
		else if( Ste ! "Fall" && Lnd == false )
		{
			Ste = "Fall";
		}

		//Collision Response
		int	Fll;	//Needed as Place Holder

		LasPos.setEq( Nde.GetPosition());
		Nde.SetPosition( Col.getCollisionResultPosition( Slc, Nde.GetPosition(), Elp, Vlc, Tri, VarPtr( Fll )));
		Nde.updateAbsolutePosition();

		//Land
		vector3df	UsrPos	= Nde.GetPosition();	//Current Node Position

		if(	vector3df<s32>( 0, LasPos.getY() + Vlc.getY(), 0 ).getDistanceFrom( vector3df<s32>( 0, UsrPos.getY(), 0 )) > 0.20 &&
			LasPos.getY() > UsrPos.getY())
		{
			FallTest	= "True";	//* Test Variable
			Lnd			= true;
			Evt			= "Fell";	//* Set Land Event For Hurt Function
			Vlc.setY( 0 );
		}

		//Knock
		else if( vector3df<s32>( 0, LasPos.getY() + Vlc.getY(), 0 ).getDistanceFrom( vector3df<s32>( 0, UsrPos.getY(), 0 )) > 0.20 &&
			LasPos.getY() < UsrPos.getY())
		{
			Lnd	= false;
			Vlc.setY( 0 );
		}
		else
		{
			FallTest	= "False";	//* Test Variable
			Lnd			= false;
		}

		/*
		Object Collision * Need to Test Mesh Collision && Object Type
		Local ObjNde:IAnimatedMeshSceneNode[]			//Animated SceneNodes
		Local UsrBox:AABbox3df = Nde.getBoundingBox()	//User Bounding Box

		ObjArr = null
		smgr.getSceneNodesFromType( ESNT_ANIMATED_MESH, ObjNde )

		for Local Obj:ISceneNode = EachIn ObjNde

			//Check if Object is Within Average Object Collision Radius
			if(	Obj.getPosition().getDistanceFrom( UsrPos ) < 200

				Test Bounding Box Collision
				if(	UsrBox.intersectsWithBox( Obj.getBoundingBox())

					Add Obj to Object Array
					AddLast ObjArr, Obj
				}
			}
		}

		if(	Lnd == true && LndCnt == false
			cout << "Landed" << endl;
			LndCnt = true
		else if( Lnd == false && LndCnt == true
			cout << "Falling" << endl;
			LndCnt = false
		}

		if(	lastpos Y plus velocity Y ! current pos Y Then Land
		if(	Lastpos Y plus Velocity Y - Current Pos Y Get Distance > 6 Then Fell

		Local VelLin:line3df = line3df( NodPos, vector3df<s32>( NodPos.getX(), NodPos.Plus( Vel ).getY() + ( Epd.getY() / 2 ), NodPos.getZ()))
		Local Isc:vector3df = vector3df

		Line.setLineFromVects( Cam.Node.getAbsolutePosition(), ..
			Line.getStart().Plus(( Cam.Node.getTarget().Minus( Line.getStart())).normalize().Mult( 1000.0 )))

		if(( Col.getCollisionPoint( ..
			VelLin, Slc, Isc, Tri ))

			if(	user::Ste == "Jump" Then user::Ste = "Stand"
			Vel.setY( 0 )
			driver.SetTransform( ETS_WORLD, matrix4.create())
			driver.draw3DTriangle( Tri, _SCOLOR( 255, 255, 0, 0 ))
		Endif
		if(	lastpos Y plus velocity Y ! current pos Y Then fell
		if(	LstPos.Plus( Vel ).getY() ! NodPos.getY()
			if(	user::Ste == "Jump" Then user::Ste = "Stand"
			Vel.setY( 0 )
		}
		*/

		//* Bumped, May need to use as function withing states.
		//Difference between: Distance between Last Position plus Velocity, Current Position, and Bump Sensitivity
		//* May have mistyped NdePos and Changed to UsrPos
		if(	vector3df<s32>( LasPos.getX() + Vlc.getX(), 0, LasPos.getZ() + Vlc.getZ()).getDistanceFrom( vector3df<s32>( UsrPos.getX(), 0, UsrPos.getZ())) > 2 )
		{
			//Bumped
			BumpTest	= "True";	//* Test Variable
			Bmp			= true;
			if(	Evt == "" ) Evt = "Bumped";
		}
		else
		{
			//Not Bumped
			BumpTest	= "False";	//* Test Variable
			Bmp			= false;
		}

		//* Incomplete //Ge t Terrain Slope
		//* Check Land and Bump Flag Then Check Terrain Slope
		if(	Lnd == false )
		{
			vector3df	TriNrm	= Tri.getNormal().normalize();						//Angle Standing on Triangle
			float		SlpAng	= vector2df<s32>(											//Surface Slope Angle
				-vector2df<s32>( 0, TriNrm.getY()).getLength(),							//XZ Distance
				vector2df<s32>( TriNrm.getX(), TriNrm.getZ()).getLength()).getAngle();	//Y Height

			if(	SlpAng > 180 && SlpAng < 225 )
			{
				vector3df		LndPos;
				triangle3df	LndTri;	//Needed as Place Holder
				line3df		FalLin	= line3df( UsrPos, UsrPos.Minus( vector3df<s32>( 0, Elp.getY() + 10, 0 )))	//User Collsion Line

				//* Need to Translate FalLin to Maps World Space
				Col.getCollisionPoint( FalLin, Map.Slc, LndPos, LndTri );	//Get Land Position
				LndPosTst	= LndPos;	//* Test Variable
				Nde.SetPosition( LndPos.Plus( vector3df<s32>( 0, Elp.getY() + 0.5, 0 )));	//Set User To Ground Level
				//* Might Try Setting the Y Velocity in the Angle of the Slope
			}
			SrfAngTst	= SlpAng;	//* Test Variable
			//Nde.SetRotation()	//Set Node Rotation to Node Angle Minus Tri Normal YX and YZ Angles
		}

		/*
		BmpLst vector3df<s32>( LstPos.getX() + Vel.getX(), 0, LstPos.getZ() + Vel.getZ()) //Estimated Distance
		BmpCur vector3df<s32>( NdePos.getX(), 0, NdePos.getZ()) //Current Distance

		if(	vector3df<s32>( LastPos.getX(), 0, LastPos.getZ()).Plus( vector3df<s32>( Velocity.getX(), 0, Velocity.getZ())).getDistanceFrom( vector3df<s32>( Node.getPosition().getX(), 0, Node.getPosition().getZ())) > 0
			if(	State == "Jump" || State == "Spring"
				Usr.Jump()
			else if( State == "Flip" || State == "Leap" || State == "Run"
				Event = "Bump"
				Usr.Hurt()
			else
				Velocity.setX( 0 )
				Velocity.setZ( 0 )
			}
		}
		*/
	}
	Climb( float Spd )
	{
		//Check Active Ladder
		for each( ladder ObjTyp in list ActObj )
		{
			if(	typeid( ObjTyp ).name() == "ladder" )
			{
				ladder		ActLad	= ladder( ObjTyp );	//Active Ladder
				vector3df	UsrRot	= Nde.GetRotation();	//User Node Rotation

				//Physics
				//*End of Ladder
				//*Next Ladder

				//Climb Ladder
				//*Set User Rotation To Face Ladder
				Nde.SetRotation( vector3df<s32>( UsrRot.getX(), 0, UsrRot.getZ()));

				//Set Velocity to Climb Direction and Speed
				Vlc.Set( 0, ConSpd * Spd * ConDir.getY(), 0 );

				//Set Position to Ladder Center
				//LadRad Rotated by Ladder Dir Around Obj Center
				Nde.SetPosition( vector3df<s32>( ActLad.Nde.GetPosition().getX(), Nde.GetPosition().getY(), ActLad.Nde.GetPosition().getZ() - ActLad.Rad ));
			}
		}
	}
	Hang()
	{
		//Set for hanging from overhangs and ceilings
		Vectr3df	UsrRot	= Nde.GetRotation();	//User Node Rotation

		//*Set User Rotation Parallel to Support
		Nde.SetRotation( vector3df<s32>( UsrRot.getX(), 0, UsrRot.getZ()));

		//*Set Velocity to Hang Direction and Speed
		Vlc.Set( 0, ConDir.getY(), 0 );

		//*Set Position to Support Center
	}
	Jump()
	{
		//Jump
		if(	Lnd == true &&
			Ste == "Stand" ||
			Ste == "Walk" ||
			Ste == "Crouch" ||
			Ste == "Crawl" )
		{
			//Physics
			Vlc.PlusEq( vector3df<s32>( 0, 7, 0 ))	;	//* Incomplete, Could use an Angle to calculate the Velocity Vector

			//Logic
			Ste	= "Jump";
		}

		//Flip
		else if( Ste == "Jump" )
		{
			//Physics
			Vlc.PlusEq( vector3df<s32>( 0, 5, 0 ));	//* Incomplete, Could use an Angle to calculate the Velocity Vector

			//Logic
			Ste	= "Flip";
		}

		//Leap
		else if( Lnd == false && Ste == "Run" )
		{
			//Physics
			matrix4	M;
			vector3df	Frc	= vector3df<s32>( 0, 7, 5 );

			M.setRotationDegrees( Nde.GetRotation());	//* Incomplete, Could use an Angle to calculate the Velocity Vector
			M.transformVect( Frc );
			user::Vlc.PlusEq( Frc );

			//Logic
			Ste	= "Leap";
		}

		//Spring
		else if( Ste == "Climb" ||
			SprTim > 0 &&
			Ste == "Jump" )
		{
			//Physics
			matrix4	M;
			vector3df	Frc	= vector3df<s32>( 0, 5, 7 );

			Nde.SetRotation( Nde.GetRotation().Minus( vector3df<s32>( 180, 0, 0 )));
			M.setRotationDegrees( Nde.GetRotation());	//* Incomplete, Could use an Angle to calculate the Velocity Vector
			M.transformVect( Frc );
			Vlc.setEq( Frc );

			//Logic
			Ste		= "Spring";
			SprTim	= 0;
		}

		//Lift
		else if( Ste == "Hang" ||
			Ste == "Climb" )
		{
			//Physics
			//Logic
		}
	}
	Use( void Obj )
	{
		//Use
		for each( void Obj in void ObjLst )
		{
			switch( typeid( Obj ).name())
			{
				//* Check Item Pickup
				case "collectable":

					//* Collect Closest Collectable
					Evt	= "PickUp";
					break;

				//* Check BackDrop Interaction
				case "ladder":
					ladder	SlcLad	= ladder( Obj );	//selected Ladder

					if(	Ste ! "Climb" && Vlc.getLength() < 1.5 )
					{
						//Check if Player is Facing a Ladder
						vector3df	UsrPos	= Nde.GetPosition();			//User Position
						vector3df	UsrRot	= Nde.GetRotation();			//User Rotation
						vector3df	LdrPos	= SlcLad.Nde.GetPosition();	//Ladder Position
						float		LdrAng	= vector2df<s32>(	//Ladder Angle
							LdrPos.getX() - UsrPos.getX(), LdrPos.getZ() - UsrPos.getZ()).getAngle() - UsrRot.getY();

						if(	LdrAng < -45 && LdrAng > 45 )
						{
							//* Step On Ladder
							Ste	= "Climb";

							//* Add Obj to ActObj List
							ObjArr[3][1];
							ObjArr.AddLast( SlcLad );
						}
					}
					//Check if Player is Climbing a Ladder
					else if( Ste == "Climb" )
					{
						//* Drop Off Ladder
					}
					break;

				case "trigger":
					//* Check if Player is Facing Trigger
					trigger	SlcTrg	= trigger( Obj );				//selected Trigger
					vector3df	UsrPos	= Nde.GetPosition();			//User Position
					vector3df	UsrRot	= Nde.GetRotation();			//User Rotation
					vector3df	TrgPos	= SlcTrg.Nde.GetPosition();	//Ladder Position
					float		TrgAng	= vector2df<s32>				//Ladder Angle
						( TrgPos.getX() - UsrPos.getX(), TrgPos.getZ() - UsrPos.getZ()).getAngle() - UsrRot.getY();

					if(	TrgAng < -45 && TrgAng > 45 )
					{
						//* Add Obj to ActObj List
						ActObj.AddLast( SlcTrg );

						//* Check if Trigger is Inactive
						//* Check Keys
							//* Check if Delay has Expired
							//* Activate Trigger
							SlcTrg.Activate();

						//* Check if Trigger is Active
						//* Check if Timer has Stopped
							//Deactivate Trigger
							SlcTrg.Deactivate();
					}
					break;

				//* Check entity Interaction
				case "enemy":

				//* Check Clan Interation
				case "friendly":

			default;
			}
		}
	}
	ActionPri()
	{
		//*Check if Melee
			//Punch *Stand/Walk/Jump and Action
				//Right or Left Jab
				//Opposite Arm Hook
				//Uppercut

			//UpperCut *Crouch/Crawl and Action
			//Dash *Run and Action
			//Stomp *Should Be in Crouch *Jump and Crouch

		//*Check if Weapon/Item
			//Swing *Stand/Walk and Action
			//Thrust *Run and Action
			//Spin *Crouch and Action

		//*Check if Ranged Weapon
		//Shoot *Stand/Walk/Jump/Crouch and Action
		if(	Amm[3] == 0 && Amm[1] > 0 )
		{
			//Ranged
			if(	WpnInf[Eqp[0]][6] )
			{
				projectile::Use( int( WpnInf[Eqp[0]][6] ));
			}
		}
	}
	ActionSec()
	{
		//*Check if Melee
			//Kick *Stand/Walk and Action
			//Jump Kick *Jump/Leap and Action
			//Slide *Run and Kick

		//Check if Item
		if(	Amm[3] == 1 && Amm[2] > 0 )
		{
			//Ranged
			if(	EqpInf[Eqp[1]][6] )
			{
				projectile::Use( int( EqpInf[Eqp[1]][6] ));
			}
		}
	}
	Hurt( int Dmg, vector2df Frc )
	{
		switch( Evt )
		{
		case "Impact":
			//Logic
			Hth	-= Dmg;

			//Animation
			//* Flash Player Visibility

			//Physical
			Vlc.PlusEq( vector3df<s32>( Frc.getX(), 0, Frc.getY()));
			Mmt	= 0;

			//Sound
			//* Player Damage Magnitude
				//Grunt
				//Shout
			break;

		case "Bumped":
			//Physical
			Mmt	= 0;

			//Animation
			//Sound
			//* Player Bump Magnitude
				//Grunt
			break;

		case "Fell":
			//Physical
			Mmt	= 0;

			//Animation
			//Sound
			break;

		default:
		}
	};

	Die()
	{
		Ste		= "Dead";	//Dead User State
		GmeSte	= "Dead";	//Dead Game State
	};

	~user();

private:
	list		Cnt;		//List of Users
	ISceneNode	NdeArr[];	//Object SceneNode Array
};
user::user( profile Nfo, vector3df Pos, vector2df Rot, IAnimatedMesh Msh, stringw Nam, stringw Skl, stringw Wpn, stringw Itm )
{
	//Client
	Msh	= Msh;
	Ste	= "Stand";
	Nde	= smgr.addAnimatedMeshSceneNode( Msh, null, null, Pos, Rot, Scl, true );
	Nde.SetPosition( Pos );
	Elp	= vector3df<s32>( 20, 40, 20 );
	Nde.setMaterialTexture( 0, this->Skn );
	Nde.setMaterialFlag( EMF_LIGHTING, false );
	Nde.setDebugDataVisible( Nfo.debug );
	Nde.setAnimationSpeed( 0 );
	if(	Nfo.input == "joystick" )
		Nfo.input.getJoystick()->rumble( 10000, 0x8000 );

	//Server
	//Register in Server Lobby
	return this;
};
user::~user()
{
	this->Nde.Remove();
	this->Msh.Remove();
	
	user::Cnt::erase( this );
	return this;
};
